/*******************************************************************************
 * Venice Noise Android Application
 * Copyright (C) 2011  Worcester Polytechnic Institute, Wesley Ripley
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; version 2
 * of the License
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * If you plan to use or modify any of this code please contact Fabio Carrera (carrera.fabio@gmail.com)
 * Also please attribute any code used in the final product to the developers. 
 * 
 * Author: Wesley Ripley (wripley@wpi.edu) 
 *******************************************************************************/
package org.venicenoise.app;
import java.io.File;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * A CursorAdapter used to display each individual piece of noise data
 * @author Wesley Ripley
 * @version 12/15/2011
 */
public class NoiseDataListAdapter extends CursorAdapter {
	
	//the date format to use to display the date
	private final static DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy 'at' h:mm a");
	//the decimal format used to display latitude and longitude
	private final static DecimalFormat coordinateFormat = new DecimalFormat("#.####");
	//the decimal format used to display the leq
	private final static DecimalFormat leqFormat = new DecimalFormat("#.#");
	
	//TODO: the thumbnail size should probably be an xml constant so it can also be used for the size of
	//		the ImageView, but this works for now
	//how big the thumbnails should be. Thumbnails are THUMB_SIZE x THUMB_SIZE
	private final static int THUMB_SIZE = 100;
	
	//whether or not the thumbnails of the photos should be shown
	private final boolean showThumbnails;
	
	/**
	 * Constructor for NoiseDataListAdapter
	 * @param context
	 * 		the context of the application
	 * @param cursor
	 * 		the cursor over the data to display
	 * @param autoRequery
	 * 		If true the adapter will call requery() on the cursor whenever it changes so the most recent data 
	 * 		is always displayed. Using true here is discouraged.
	 * @param showThumb
	 * 		Whether or not to show thumbnails of the photos for each piece of data
	 */
	public NoiseDataListAdapter(Context context, Cursor cursor, boolean autoRequery, boolean showThumb)
	{
		super(context,cursor,autoRequery);
		showThumbnails = showThumb;
	}
	/**
	 *	Constructor for NoiseDataListAdapter
	 * @param context
	 * 		the context of the application
	 * @param cursor
	 * 		the cursor over the data to display
	 * @param autoRequery
	 * 		If true the adapter will call requery() on the cursor whenever it changes so the most recent data 
	 * 		is always displayed. Using true here is discouraged.
	 */
	public NoiseDataListAdapter(Context context, Cursor cursor, boolean autoRequery)
	{
		this(context,cursor,autoRequery,true);
	}

	/**
	 * Bind an existing view to the data pointed to by cursor
	 */
	@Override
	public void bindView(View view, Context context, Cursor cursor) {
		NoiseData data = SubmissionQue.cursorToData(cursor);//turn the cursor into noise data
		//get each piece of the view
		ImageView image = (ImageView)view.findViewById(R.id.submissionImage);
		TextView time = (TextView)view.findViewById(R.id.submissionTime);
		TextView description = (TextView)view.findViewById(R.id.submissionDescription);
		TextView lat = (TextView)view.findViewById(R.id.submissionLat);
		TextView longi = (TextView)view.findViewById(R.id.submissionLong);
		if(!showThumbnails)
		{
			image.setVisibility(View.GONE);
		}
		else if(image != null && data.getPhotoFile() != null)
		{
			Bitmap imageBitmap = fileToThumnail(data.getPhotoFile());
			if(imageBitmap != null)
			{
				image.setImageBitmap(imageBitmap);
			}
			else
			{
				image.setVisibility(View.INVISIBLE);
			}
		}
		else
		{
			image.setVisibility(View.INVISIBLE);
		}
		if(time != null)
		{
			Date date = new Date(data.getTimestamp()*1000L);
			time.setText(dateFormat.format(date));
		}
		if(description != null)
		{
			description.setText(data.getDescription());
		}
		if(lat != null && data.getLocationService() != null && data.getLocationService().locationAvailable())
		{
			lat.setText(coordinateFormat.format(data.getLocationService().getLocation().getLatitude()));
		}
		if(longi != null && data.getLocationService() != null && data.getLocationService().locationAvailable())
		{
			longi.setText(coordinateFormat.format(data.getLocationService().getLocation().getLongitude()));
		}
		//show the leq only if available
		View leqLabel = view.findViewById(R.id.submissionLeqLabel);
		TextView leqText = (TextView)view.findViewById(R.id.submissionLeq);
		if(leqLabel != null && leqText != null)
		{
			double leq = data.getLeq();
			if(leq != 0)
			{
				leqLabel.setVisibility(View.VISIBLE);
				leqText.setVisibility(View.VISIBLE);
				leqText.setText(leqFormat.format(leq));
			}
			else
			{
				leqLabel.setVisibility(View.GONE);
				leqText.setVisibility(View.GONE);
			}
		}
	}

	/**
	 * Makes a new view to hold the data pointed to by cursor.
	 */
	@Override
	public View newView(Context context, Cursor cursor, ViewGroup parent) {
		 final LayoutInflater inflater = LayoutInflater.from(context);
		 return inflater.inflate(R.layout.submission, parent, false);
	}
	
	/**
	 * Generate a Bitmap thumbnail of the given image file
	 * @param imageFile
	 * 		the file to make the thumbnail of
	 * @return
	 * 		the Bitmap thumbnail
	 */
	private Bitmap fileToThumnail(File imageFile)
	{
		try
		{
			BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
			//to save memory load the smallest sample image that is still larger than desired size
			bitmapOptions.inSampleSize = ImageUtil.maxInSampleSize(ImageUtil.getImageFileDimensions(imageFile), 
																	new ImageUtil.Dimension(THUMB_SIZE,THUMB_SIZE));
			//bitmapOptions.inSampleSize = 16;
			Bitmap bitmapImage = BitmapFactory.decodeFile(imageFile.getAbsolutePath(),bitmapOptions);
			int width = bitmapImage.getWidth();
			int height = bitmapImage.getHeight();
			//scale the bitmap to the same size in order to make it mutable
			bitmapImage = Bitmap.createScaledBitmap(bitmapImage, width, height, false);
			if(width > height) //if wide image
			{
				//crop left portion so image is a square height x height
				bitmapImage = Bitmap.createBitmap(bitmapImage, 0, 0, height, height);
			}
			else if (height > width)//if tall image
			{
				//crop bottom portion so image is a square width x width
				bitmapImage = Bitmap.createBitmap(bitmapImage, 0, 0, width, width);
			}
			//scale down to the correct size
			bitmapImage = Bitmap.createScaledBitmap(bitmapImage, THUMB_SIZE, THUMB_SIZE, false);
			return bitmapImage;
		}catch(OutOfMemoryError e)
		{
			//if we don't have memory to load the picture don't load it
			return null;
		}
	}
	
}
